package com.zjt.smart.mvp.view;

import android.support.annotation.Nullable;

import com.zjt.smart.api.server.BaseServer;

import java.util.ArrayList;
import java.util.List;

/**
 * 串行加载LoadView
 */

public class SerialLoadView implements LoadView<Object> {
    private LoadView<Object> loadView;
    private List<SerialLoader> list;
    private List<Object> result;
    private long cacheTime = 0;

    public SerialLoadView(LoadView<Object> loadView) {
        this.loadView = loadView;
        list = new ArrayList<>();
        result = new ArrayList<>();
    }

    public void addLoader(SerialLoader loader) {
        list.add(loader);
    }

    public void startLoading(boolean fromCache) {
        result.clear();
        cacheTime = 0;
        executeLoader(0, list, fromCache);
    }

    private void executeLoader(int index, List<SerialLoader> list, boolean fromCache) {
        if (index >= list.size()) {
            if (result.size() == 0) {
                onFail(BaseServer.NO_MORE, "No more");
                return;
            }
            if (fromCache) {
                onCache(cacheTime, result);
            } else {
                onSuccess(result);
            }
            return;
        }
        SerialLoader loader = list.get(index);
        LoadView<Object> serialLoadView = new LoadView<Object>() {
            @Nullable
            @Override
            public void onSuccess(List<Object> data) {
                addData(data);
                executeLoader(index + 1, list, fromCache);
            }

            @Override
            public void onCache(long cacheTime, List<Object> data) {
                if (cacheTime == 0) {
                    onCache(0, null);
                    return;
                }
                if (cacheTime > SerialLoadView.this.cacheTime) {
                    SerialLoadView.this.cacheTime = cacheTime;
                }
                addData(data);
                executeLoader(index + 1, list, fromCache);
            }

            @Override
            public void onFail(int errorCode, String errorMsg) {
                if (errorCode != BaseServer.NO_MORE) {
                    onFail(BaseServer.DATA_INCOMPLETE, "Data incomplete in parallel request");
                    return;
                }
                executeLoader(index + 1, list, fromCache);
            }
        };
        loader.loadSerial(serialLoadView, fromCache);
    }

    private synchronized void addData(List<Object> data) {
        if (data == null || data.size() == 0) {
            return;
        }
        result.addAll(data);
    }

    @Nullable
    @Override
    public void onSuccess(List<Object> data) {
        if (loadView != null) {
            loadView.onSuccess(data);
        }
    }

    @Override
    public void onCache(long cacheTime, List<Object> data) {
        if (loadView != null) {
            loadView.onCache(cacheTime, data);
        }
    }

    @Override
    public void onFail(int errorCode, String errorMsg) {
        if (loadView != null) {
            loadView.onFail(errorCode, errorMsg);
        }
    }

    public interface SerialLoader<ParallelType> extends Loader {

        void loadSerial(LoadView<ParallelType> loadView, boolean fromCache);
    }

}
